package evo;

import gui.Console;
import ids.PlacementMove;
import ids.PlacementState;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import ns2.Topology;

import opt.SimAnneal;
import util.FileReader;
import util.SSIDException;

public class DynamicPlacement {

	TechInit tob;

	FileReader fileReader;

	BufferedWriter output;

	PlacementState lastbest;

	Console console;

	public DynamicPlacement(TechInit ti, FileReader rtf, String output)
			throws IOException {
		this.tob = ti;
		this.fileReader = rtf;
		this.console = new Console();
		this.output = new BufferedWriter(new FileWriter(output));
	}

	public void run(float interval) throws IOException {
		Topology topology = this.fileReader.getTopology();
		// topology.initialise(this.rtf.getRtTraces(),
		// this.rtf.getStart_time());
		// topology.initialise(fileReader.getTopologyfile());
		float start = 0;
		float end = 0;
		float terminate = this.fileReader.getTrafficTraces().lastElement().time;
		// boolean quiet = true;

		while (end < terminate) {
			end = end + interval;
			topology.update(this.fileReader.getTrafficTraces(), start, end);
			PlacementState[] states = new PlacementState[tob.getNumberOfRuns()];
			for (int i = 0; i < this.tob.getNumberOfRuns(); i++) {
				SimAnneal sa = new SimAnneal();
				sa.setConsole(this.console);

				PlacementState plcState = new PlacementState();
				PlacementMove plcMove = new PlacementMove();

				this.tob.setSeed(this.tob.getSeed() + i);
				plcState.initialise(tob);

				this.tob.setState(plcState);
				this.tob.setMove(plcMove);

				sa.initialise(this.tob);
				sa.doSimulatedAnnealing();

				plcState = sa.getBestStateSoFar();
				states[i] = plcState.copy();
				this.output.write(plcState.print() + '\n');
			}
			System.out.println('\n' + "Based on data during from time " + start
					+ " till " + end);
			if ((this.getBestStateFrom(states).getFitness() > 0)
					|| (start == 0)) {
				System.out.println(this.getBestStateFrom(states).print());
				this.lastbest = this.getBestStateFrom(states);
			} else {
				this.lastbest.setFitness(0);
				System.out.println(this.lastbest.print());
			}
			start = end;
		}
		this.output.close();
	}

	private PlacementState getBestStateFrom(PlacementState[] states) {
		int best = 0;
		for (int i = 0; i < states.length; i++) {
			if (states[i].getFitness() > states[best].getFitness())
				best = i;
		}
		return states[best];
	}

	public void setConsole(Console console) {
		this.console = console;
	}

	public static void main(String[] args) throws IOException {
		FileReader reader = null;
		TechInit ti = null;
		String output = new String();
		float interval = 1;
		try {
			if (args.length != 6)
				throw new SSIDException(
						"6 parameters are required to run the program.\n");
			else {
				reader = new FileReader(new File(args[0]), new File(args[1]),
						new File(args[2]));
				reader.readTraceFile();
				reader.readTopologyFile();
				reader.readSensorSettings();
				// reader.process();
				ti = new TechInit();
				ti.processParamsFile(new File(args[3]));
				ti.setNumberOfRuns(new Integer(args[4]));
				interval = new Float(args[5]);
			}
		} catch (SSIDException e) {
			System.err.print(e.getMessage());
			System.err.print(e.getDynamicPlacementUsage());
			System.exit(1);
		}
		DynamicPlacement search = new DynamicPlacement(ti, reader, output);
		search.run(interval);
	}
}